package winOrDie.Net.Client;

import java.io.IOException;
import java.net.Socket;
import java.util.Iterator;
import java.util.Vector;

import rice.p2p.commonapi.Node;

import winOrDie.Net.WoD_Net_Protocol_ASCII;
import winOrDie.Net.WoD_TCP_Channel;
import winOrDie.Net.WoD_TCP_Channel_Event;
import winOrDie.Net.WoD_TCP_Channel_Listener;
import winOrDie.Net.P2P.WoD_ScribeContent;
import winOrDie.Net.P2P.WoD_Scribe_Channel;
import winOrDie.Net.P2P.WoD_Scribe_Channel_Event;
import winOrDie.Net.P2P.WoD_Scribe_Channel_Listener;
import winOrDie.Net.Server.WoD_Server_ControlChannel_Event;

public class WoD_Client_ControlChannel  
implements WoD_TCP_Channel_Listener, WoD_Scribe_Channel_Listener
{
	/**
	 * Channel type
	 */
	public static class Channel_Type
	{
		public static final int Channel_Type_TCP = 0;
		public static final int Channel_Type_Scribe = 1;
	}

	private int channel_Type = -1;
	
	
	/**
	 * The {@link WoD_TCP_Channel}
	 */
	private WoD_TCP_Channel woDTCPChannel = null;
	
	private WoD_Scribe_Channel woDScribeChannel = null;
	
	
	/**
	 * Listeners vector
	 */
	private Vector<WoD_Client_ControlChannel_Listener> listeners = null;
	
	public WoD_Client_ControlChannel(Node node) 
	{
		// Set channel type
		channel_Type = Channel_Type.Channel_Type_Scribe;
		
		woDScribeChannel = new WoD_Scribe_Channel(node);
		woDScribeChannel.add_WoD_Scribe_Channel_Listener(this);
		
		/*
		 * Initialize listeners vector
		 */
		listeners = new Vector<WoD_Client_ControlChannel_Listener>();
	}
	
	public WoD_Client_ControlChannel(Socket socket) throws Exception 
	{
		channel_Type = Channel_Type.Channel_Type_TCP;
		
		/*
		 * Initialize WoD_TCP_Channel object
		 */
		woDTCPChannel = new WoD_TCP_Channel(socket);
		woDTCPChannel.add_WoD_TCP_Channel_Listener(this);
		
		/*
		 * Initialize listeners vector
		 */
		listeners = new Vector<WoD_Client_ControlChannel_Listener>();
		
	}

	
	/**
	 * This public method starts this {@link WoD_Client_ControlChannel}
	 */
	public void start_WoD_Client_ControlChannel()
	{
		switch (channel_Type) {
		case Channel_Type.Channel_Type_TCP:
			// Start TCP Channel thread
			woDTCPChannel.start_WoD_TCP_Channel();
			break;
		
		case Channel_Type.Channel_Type_Scribe:
			// Start Scribe Channel thread
			woDScribeChannel.start_Wod_Scribe_Channel();
			woDScribeChannel.subscribe();
			break;
		
		default:
			break;
		}
	}
	
	
	
	public synchronized void add_WoD_Client_ControlChannel_Listener(WoD_Client_ControlChannel_Listener listener)
	{
		listeners.add(listener);
	}
	
	public synchronized void remove_WoD_Client_ControlChannel_Listener(WoD_Client_ControlChannel_Listener listener)
	{
		listeners.remove(listener);
	}
	
	
	protected void fireEvent(WoD_Client_ControlChannel_Event event)
	{
//		Iterator<WoD_Client_ControlChannel_Listener> iterator = listeners.iterator();
//		synchronized (iterator) {
//			while (iterator.hasNext()) {
//				iterator.next().notify_Event_WoD_Client_ControlChannel(event);
//				
//			}
//		}

		
		for (WoD_Client_ControlChannel_Listener listener : listeners) {
			listener.notify_Event_WoD_Client_ControlChannel(event);
		}

	}
	

	
	private void parse_Control_Message(String message)
	{
		String header = message.split(" ")[0];
		
		WoD_Client_ControlChannel_Event event = null;
		
		if (header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_KO))
		{
			event = new WoD_Client_ControlChannel_Event(this);
			event.setEvent_Type(WoD_Client_ControlChannel_Event.JOIN_GAME_KO);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_OK))
		{
			event = new WoD_Client_ControlChannel_Event(this);
			event.setEvent_Type(WoD_Client_ControlChannel_Event.JOIN_GAME_OK);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Chat))
		{
			event = new WoD_Client_ControlChannel_Event(this);
			event.setEvent_Type(WoD_Client_ControlChannel_Event.CHAT);
			event.setData(message);
			fireEvent(event);
		}
	}
	
	
	public synchronized void sendData(String message) throws Exception
	{
		try {
			//dataOutputStream.writeUTF(message);
			woDTCPChannel.sendData(message);
		} catch (IOException e) {
			Exception exception = new Exception("Error sending data. " + e.getMessage());
			throw exception;
		}
	}
	
	
	public void on_WoD_TCP_Channel_Change(WoD_TCP_Channel_Event event) 
	{
		switch (event.getEvent_Type()) 
		{
		case WoD_TCP_Channel_Event.MESSAGE_RECEIVED:
			parse_Control_Message(
					String.valueOf(event.getData()) 
					);
			break;

		default:
			break;
		}
		
	}
	
	

	public void on_WoD_Scribe_Channel_Change(WoD_Scribe_Channel_Event event) 
	{
		

		// Get WoD_ScribeContent
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent) event.getData();

		switch (event.getEvent_Type()) 
		{

		/**
		 * This node is the Scribe topic Root.
		 * Shall send game information to all peers.
		 */
		case WoD_Scribe_Channel_Event.I_AM_ROOT:
			WoD_Client_ControlChannel_Event controlChannelEvent = new WoD_Client_ControlChannel_Event(this);
			controlChannelEvent.setEvent_Type(WoD_Client_ControlChannel_Event.P2P_I_AM_ROOT);
			fireEvent(controlChannelEvent);
			break;


			/**
			 * If it's application message parse it.
			 */
		case WoD_Scribe_Channel_Event.MESSAGE_RECEIVED:
			parse_Control_Message(woDScribeContent.getMessage().toString());
			break;


		default:
			break;
		}
		
	}

	public WoD_Scribe_Channel getWoDScribeChannel() {
		return woDScribeChannel;
	}
	
	
	
	
}
